package com.example.demo.dao

import com.example.demo.constant.AddressConstant
import com.example.demo.expansion.awaitLocalConsumer
import com.example.demo.expansion.conn
import io.vertx.core.eventbus.EventBus
import io.vertx.core.eventbus.Message
import io.vertx.core.json.JsonArray
import io.vertx.core.json.JsonObject
import io.vertx.kotlin.core.json.get
import io.vertx.kotlin.coroutines.awaitResult
import io.vertx.mysqlclient.MySQLPool
import io.vertx.sqlclient.*
import org.slf4j.LoggerFactory

private val logger = LoggerFactory.getLogger("dao.common")

suspend fun dbQueryEvent(eventBus: EventBus, pool: MySQLPool) {
  eventBus.awaitLocalConsumer<String>(AddressConstant.DB_QUERY) {
    dbQueryItemHandler(it, pool)
  }
}


suspend fun dbQueryEventWithParams(eventBus: EventBus, pool: MySQLPool) {
  eventBus.awaitLocalConsumer<JsonObject>(AddressConstant.DB_QUERY_PARAMS) {
    dbQueryItemHandlerWithParams(it, pool)
  }
}

private suspend fun dbQueryItemHandler(message: Message<String>, pool: MySQLPool) {
  pool.conn({ conn ->
    val sql = message.body()
    logger.info("执行查询：$sql")
    val rowSet = awaitResult<RowSet<Row>> { conn.query(sql).execute(it) }
    val list = rowSet.map { row ->
      row.toJson()
    }
    message.reply(JsonArray(list))
  }, {
    message.reply(JsonArray())
  })
}

private suspend fun dbQueryItemHandlerWithParams(message: Message<JsonObject>, pool: MySQLPool) {
  pool.conn({ conn ->
    val body = message.body()
    var sql = body.getString("sql")
    val params = body.getJsonObject("params")
    logger.info("执行查询：$sql，参数：$params")
    val pList = ArrayList<Any>()
    sql = handleParams(sql, params, pList)
    val rowSet = awaitResult<RowSet<Row>> { conn.preparedQuery(sql).execute(Tuple.tuple(pList), it) }
    val list = rowSet.map { row ->
      row.toJson()
    }
    message.reply(JsonArray(list))
  }, {
    message.reply(JsonArray())
  })
}

fun handleParams(sql: String, params: JsonObject, pList: ArrayList<Any>): String {
  if (params.isEmpty) {
    return sql
  }
  val matchList = findAll(sql)
  var tsql = sql
  matchList.forEach {
    val value = it.value
    val key = value.replace("#{", "").replace("}", "")
    pList.add(params[key])
    tsql = tsql.replace(value, " ? ")
  }
  return tsql
}

private fun findAll(sql: String): List<MatchResult> = """#\{\w+}""".toRegex().findAll(sql).toList()



